#include "CNoteDisplayManager.h"
#include "QNoteViewWindow.h"
#include <QDebug>

CNoteDisplayManager::CNoteDisplayManager(Note& note, MApplicationPage* parent)
    : m_hEvernote(QvernoteAPI::Instance()), m_lastOffset(0), m_parent(parent)
{
    //noteDisplayWidgetTable[Main].note = new Note();
    //noteDisplayWidgetTable[Secondary].note = new Note();

    //memcpy(noteDisplayWidgetTable[Main].note, &note, sizeof(Note));
    noteDisplayWidgetTable[Main].note = note;
    noteDisplayWidgetTable[Main].noteWidget = new CNoteDisplayWidget(note);
    noteDisplayWidgetTable[Secondary].noteWidget = NULL;

    noteDisplayWidgetTable[Main].noteAnim = new QPropertyAnimation(noteDisplayWidgetTable[Main].noteWidget, "geometry");
    noteDisplayWidgetTable[Main].noteAnim->setEasingCurve(QEasingCurve::OutQuad);

    m_parent->setCentralWidget(noteDisplayWidgetTable[Main].noteWidget);
    noteDisplayWidgetTable[Main].noteWidget->render();
    noteDisplayWidgetTable[Main].noteWidget->GetRenderer()->page()->mainFrame()->addToJavaScriptWindowObject("JSApi",m_parent);
    m_noteInfoPanel = new CNoteInfoPanel(m_parent);
    m_noteInfoPanel->setNote(note);
}

CNoteDisplayManager::~CNoteDisplayManager()
{
    destroyAnimation(Main);
    destroyWidget(Secondary);
}

void CNoteDisplayManager::Shift(int offset, int delta)
{
    m_animationGroup.stop();

    if(offset > m_lastOffset)
        m_currentPanDirection = Right;
    else if (offset < m_lastOffset)
        m_currentPanDirection = Left;

    /* We moving the note right */
    if(offset > 0 && m_currentPanDirection == Right)
    {
        if(noteDisplayWidgetTable[Secondary].noteWidget == NULL)
        {
            m_noteInfoPanel->animHide();
            appendWidgetLeft();

            // Save the shift position of main widget;
            m_initialPanDirection = m_currentPanDirection;
        }
    }

    if(offset < 0 && m_currentPanDirection == Left)
    {
        if(noteDisplayWidgetTable[Secondary].noteWidget == NULL)
        {
            m_noteInfoPanel->animHide();
            appendWidgetRight();

            // Save the shift position of main widget;
            m_initialPanDirection = m_currentPanDirection;
        }
    }

    getMainWidget()->moveBy(delta, 0);

    if(getSecondaryWidget())
        getSecondaryWidget()->moveBy(delta, 0);

    m_lastOffset = offset;
}

bool CNoteDisplayManager::isSwitchWidgetNeeded()
{
    return (m_initialPanDirection == m_currentPanDirection);
}

void CNoteDisplayManager::switchWidget()
{
    QObject::disconnect(&m_animationGroup, SIGNAL(finished()), this, SLOT(doSwitchWidget()));
    QObject::disconnect(&m_animationGroup, SIGNAL(finished()), this, SLOT(doResetWidget()));

    if(!getSecondaryWidget())
        return resetWidget();

    QRectF widgetGeom = getMainWidget()->geometry();
    noteDisplayWidgetTable[Main].noteAnim->setStartValue(widgetGeom);
    noteDisplayWidgetTable[Main].noteAnim->setEndValue(QRect(
            (m_currentPanDirection == Right)? widgetGeom.width() : -widgetGeom.width(),
            widgetGeom.y(),
            widgetGeom.width(),
            widgetGeom.height()));

    m_animationGroup.addAnimation(noteDisplayWidgetTable[Main].noteAnim);

    widgetGeom = getSecondaryWidget()->geometry();
    noteDisplayWidgetTable[Secondary].noteAnim->setStartValue(widgetGeom);
    noteDisplayWidgetTable[Secondary].noteAnim->setEndValue(QRect(
            0,
            widgetGeom.y(),
            widgetGeom.width(),
            widgetGeom.height()));

    m_animationGroup.addAnimation(noteDisplayWidgetTable[Secondary].noteAnim);

    QObject::connect(&m_animationGroup, SIGNAL(finished()), this, SLOT(doSwitchWidget()));

    m_animationGroup.start();
}

void CNoteDisplayManager::resetWidget()
{
    QObject::disconnect(&m_animationGroup, SIGNAL(finished()), this, SLOT(doSwitchWidget()));
    QObject::disconnect(&m_animationGroup, SIGNAL(finished()), this, SLOT(doResetWidget()));

    QRectF widgetGeom = getMainWidget()->geometry();
    noteDisplayWidgetTable[Main].noteAnim->setStartValue(widgetGeom);
    noteDisplayWidgetTable[Main].noteAnim->setEndValue(QRect(
            0,
            widgetGeom.y(),
            widgetGeom.width(),
            widgetGeom.height()));

    m_animationGroup.addAnimation(noteDisplayWidgetTable[Main].noteAnim);

    if(getSecondaryWidget())
    {
        widgetGeom = getSecondaryWidget()->geometry();
        noteDisplayWidgetTable[Secondary].noteAnim->setStartValue(widgetGeom);
        noteDisplayWidgetTable[Secondary].noteAnim->setEndValue(QRect(
                (m_currentPanDirection == Right)? widgetGeom.width() : -widgetGeom.width(),
                widgetGeom.y(),
                widgetGeom.width(),
                widgetGeom.height()));

        m_animationGroup.addAnimation(noteDisplayWidgetTable[Secondary].noteAnim);
    }

    QObject::connect(&m_animationGroup, SIGNAL(finished()), this, SLOT(doResetWidget()));

    m_animationGroup.start();
}

void CNoteDisplayManager::appendWidgetLeft()
{
    //Note note;
    qDebug() << "AppendWidgetLeft";
    if(m_hEvernote->getPrevNote(noteDisplayWidgetTable[Main].note.guid, noteDisplayWidgetTable[Secondary].note) == false ||
       m_hEvernote->getNoteContent(noteDisplayWidgetTable[Secondary].note) == false)
    {
            qgraphicsitem_cast<QNoteViewWindow*>(m_parent)->displayError(trUtf8("Unable to load note"), QString(m_hEvernote->getLastErrorString().c_str()));
            return;
    }


    noteDisplayWidgetTable[Secondary].noteWidget = new CNoteDisplayWidget(noteDisplayWidgetTable[Secondary].note, m_parent);
    noteDisplayWidgetTable[Secondary].noteAnim = new QPropertyAnimation(noteDisplayWidgetTable[Secondary].noteWidget, "geometry");
    noteDisplayWidgetTable[Secondary].noteAnim->setEasingCurve(QEasingCurve::OutQuad);
    QRectF mainWidgetGeometry = getMainWidget()->geometry();
    noteDisplayWidgetTable[Secondary].noteWidget->setGeometry(mainWidgetGeometry.x() - mainWidgetGeometry.width(),
                                                   mainWidgetGeometry.y(), mainWidgetGeometry.width(), mainWidgetGeometry.height());
    noteDisplayWidgetTable[Secondary].noteWidget->render();
    noteDisplayWidgetTable[Secondary].noteWidget->GetRenderer()->page()->mainFrame()->addToJavaScriptWindowObject("JSApi",m_parent);
}

void CNoteDisplayManager::appendWidgetRight()
{
    //Note note;
    qDebug() << "AppendWidgetRight";

    if(m_hEvernote->getNextNote(noteDisplayWidgetTable[Main].note.guid, noteDisplayWidgetTable[Secondary].note) == false ||
       m_hEvernote->getNoteContent(noteDisplayWidgetTable[Secondary].note) == false)
    {
            qgraphicsitem_cast<QNoteViewWindow*>(m_parent)->displayError(trUtf8("Unable to load note"), QString(m_hEvernote->getLastErrorString().c_str()));
            return;
    }

    noteDisplayWidgetTable[Secondary].noteWidget = new CNoteDisplayWidget(noteDisplayWidgetTable[Secondary].note, m_parent);
    noteDisplayWidgetTable[Secondary].noteAnim = new QPropertyAnimation(noteDisplayWidgetTable[Secondary].noteWidget, "geometry");
    noteDisplayWidgetTable[Secondary].noteAnim->setEasingCurve(QEasingCurve::OutQuad);
    QRectF mainWidgetGeometry = getMainWidget()->geometry();
    noteDisplayWidgetTable[Secondary].noteWidget->setGeometry(mainWidgetGeometry.x() + mainWidgetGeometry.width(),
                                                   mainWidgetGeometry.y(), mainWidgetGeometry.width(), mainWidgetGeometry.height());
    noteDisplayWidgetTable[Secondary].noteWidget->render();
    noteDisplayWidgetTable[Secondary].noteWidget->GetRenderer()->page()->mainFrame()->addToJavaScriptWindowObject("JSApi",m_parent);
}

CNoteDisplayWidget* CNoteDisplayManager::getMainWidget()
{
    return noteDisplayWidgetTable[Main].noteWidget;
}

CNoteDisplayWidget* CNoteDisplayManager::getSecondaryWidget()
{
    return noteDisplayWidgetTable[Secondary].noteWidget;
}

void CNoteDisplayManager::destroyWidget(NoteWidgetId widgetId)
{
    if(noteDisplayWidgetTable[widgetId].noteWidget)
        delete noteDisplayWidgetTable[widgetId].noteWidget;

    destroyAnimation(widgetId);
    noteDisplayWidgetTable[widgetId].noteWidget = NULL;
}

void CNoteDisplayManager::destroyAnimation(NoteWidgetId widgetId)
{
    //if(noteDisplayWidgetTable[widgetId].noteAnim)
    //{
        m_animationGroup.removeAnimation(noteDisplayWidgetTable[widgetId].noteAnim);
        qDebug() << "CNoteDisplayManager::destroyAnimation()" << widgetId;

        if(noteDisplayWidgetTable[widgetId].noteAnim) delete noteDisplayWidgetTable[widgetId].noteAnim;

    // noteDisplayWidgetTable[widgetId].noteAnim = NULL;
    //}
}

void CNoteDisplayManager::doSwitchWidget()
{
    Note tmp;
    QPropertyAnimation* tmpAnim;

    if(getSecondaryWidget())
    {
        qDebug() << "CNoteDisplayManager::doSwitchWidget()";

        noteDisplayWidgetTable[Main].noteWidget = noteDisplayWidgetTable[Secondary].noteWidget;

        tmp = noteDisplayWidgetTable[Main].note;
        noteDisplayWidgetTable[Main].note = noteDisplayWidgetTable[Secondary].note;
        noteDisplayWidgetTable[Secondary].note = tmp;

        // Remove animations from group and switch between them
        //tmpAnim = (QPropertyAnimation*)m_animationGroup.takeAnimation(Main);
        noteDisplayWidgetTable[Main].noteAnim = (QPropertyAnimation*)m_animationGroup.takeAnimation(Secondary);//noteDisplayWidgetTable[Secondary].noteAnim;
        //noteDisplayWidgetTable[Secondary].noteAnim = tmpAnim;

        // delete old Main animation
        m_animationGroup.clear();
        //destroyAnimation(Secondary);

        m_parent->setCentralWidget(getMainWidget());
        noteDisplayWidgetTable[Secondary].noteWidget = NULL;
        m_noteInfoPanel->setNote(noteDisplayWidgetTable[Main].note);
        m_lastOffset = 0;
    }

    //m_noteInfoPanel->animShow();

    qDebug() << "CNoteDisplayManager::doSwitchWidget() done" << "anims: " << m_animationGroup.animationCount();
    emit animationDone(Qt::PanGesture);
}

void CNoteDisplayManager::doResetWidget()
{
    if(getSecondaryWidget())
        destroyWidget(Secondary);

    m_lastOffset = 0;

   //m_noteInfoPanel->animShow();

    qDebug() << "CNoteDisplayManager::doResetWidget() done";
    emit animationDone(Qt::PanGesture);
}

Note& CNoteDisplayManager::GetCurrentNote()
{
    return noteDisplayWidgetTable[Main].note;
}

void  CNoteDisplayManager::HideInfoPane()
{
    m_noteInfoPanel->animHide();
}
